package com.slwu.util;


import cn.hutool.core.util.ObjectUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 时间工具类
 *
 * @author whb
 */
public class DateUtil {

    public static final String FULL_TIME_PATTERN = "yyyyMMddHHmmss";

    public static final String FULL_TIME_SPLIT_PATTERN = "yyyy-MM-dd HH:mm:ss";

    public static final String CST_TIME_PATTERN = "EEE MMM dd HH:mm:ss zzz yyyy";

    public static final String yyyyMMdd = "yyyyMMdd";
    public static final String yyyy = "yyyy";

    public static final String DATE_SPLIT_PATTERN = "yyyy-MM-dd";

    public static final String DATE_YEARMM_PATTERN = "yyyy-MM";

    public static Pattern VALIDATE_DATE = Pattern.compile("\\d{4}+\\d{1,2}+\\d{1,2}+");

    /**
     * 格式化时间，格式为 yyyyMMddHHmmss
     *
     * @param localDateTime LocalDateTime
     * @return 格式化后的字符串
     */
    public static String formatFullTime(LocalDateTime localDateTime) {
        return formatFullTime(localDateTime, FULL_TIME_PATTERN);
    }

    /**
     * 根据传入的格式，格式化时间
     *
     * @param localDateTime LocalDateTime
     * @param format        格式
     * @return 格式化后的字符串
     */
    public static String formatFullTime(LocalDateTime localDateTime, String format) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
        return localDateTime.format(dateTimeFormatter);
    }

    /**
     * 根据传入的格式，格式化时间
     *
     * @param date   Date
     * @param format 格式
     * @return 格式化后的字符串
     */
    public static String getDateFormat(Date date, String format) {

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format, Locale.CHINA);
        return simpleDateFormat.format(date);
    }

    /**
     * 格式化 CST类型的时间字符串
     *
     * @param date   CST类型的时间字符串
     * @param format 格式
     * @return 格式化后的字符串
     * @throws ParseException 异常
     */
    public static String formatCstTime(String date, String format) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(CST_TIME_PATTERN, Locale.US);
        Date usDate = simpleDateFormat.parse(date);
        return getDateFormat(usDate, format);
    }

    /**
     * 格式化 Instant
     *
     * @param instant Instant
     * @param format  格式
     * @return 格式化后的字符串
     */
    public static String formatInstant(Instant instant, String format) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        return localDateTime.format(DateTimeFormatter.ofPattern(format));
    }

    public static String formatFromTo(String date, String from, String to) {
        LocalDate parse = LocalDate.parse(date, DateTimeFormatter.ofPattern(from));
        return parse.format(DateTimeFormatter.ofPattern(to));
    }

    public static String formatLocalDate(LocalDate localDate, String format) {
        if (ObjectUtil.isNull(localDate)) {
            return "";
        }
        return localDate.format(DateTimeFormatter.ofPattern(format));
    }

    /**
     * 判断当前时间是否在指定时间范围
     *
     * @param from 开始时间
     * @param to   结束时间
     * @return 结果
     */
    public static boolean between(LocalTime from, LocalTime to) {
        LocalTime now = LocalTime.now();
        return now.isAfter(from) && now.isBefore(to);
    }

    /**
     * 判断日期字符串是否符合指定日期格式
     * @param dateStr 日期字符串
     * @param format 日期格式
     * @return 结果
     */
    public static boolean isFormat(String dateStr, String format) {
        if (ObjectUtil.isEmpty(dateStr)) {
            return false;
        }
        if (ObjectUtil.isEmpty(format)) {
            format = DATE_SPLIT_PATTERN;
        }

        try {
            LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(format));
            return true;
        } catch (Exception e) {
            return false;
        }

    }

    public static boolean isYear(String yearStr, int thisYear) {
        if (ObjectUtil.isEmpty(yearStr)) {
            return false;
        }

        if (yearStr.length() != 4) {
            return false;
        }

        int year;

        try {
            year = Integer.parseInt(yearStr);

            if (year > thisYear) {
                return false;
            }
            return true;
        } catch (Exception e) {
            return false;
        }

    }

    /**
     * 判断指定日期格式的日期字符串是否在指定时间内
     * @param date 日期字符串
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @param format 日期格式
     * @return 结果
     */
    public static boolean isBetween(String date, String startDate, String endDate, String format) {
        if (ObjectUtil.isEmpty(format)) {
            format = DATE_SPLIT_PATTERN;
        }

        LocalDate localDate = LocalDate.parse(date, DateTimeFormatter.ofPattern(format));
        LocalDate startLocalDate = LocalDate.parse(startDate, DateTimeFormatter.ofPattern(format));
        LocalDate endLocalDate = LocalDate.parse(endDate, DateTimeFormatter.ofPattern(format));

        return localDate.isAfter(startLocalDate) && localDate.isBefore(endLocalDate);

    }

    /**
     * 获取指定日期格式的日期字符串的年月日(y: 年；m: 月；d: 日)
     * @param date 日期字符串
     * @param format 日期格式
     * @param type y: 年；m: 月；d: 日
     * @return 年月日
     */
    public static int getYMD(String date, String format, String type) {
        if (ObjectUtil.isEmpty(format)) {
            format = DATE_SPLIT_PATTERN;
        }

        LocalDate parse = LocalDate.parse(date, DateTimeFormatter.ofPattern(format));

        if ("y".equals(type)) {
            return parse.getYear();
        } else if ("m".equals(type)){
            return parse.getMonthValue();
        } else if ("d".equals(type)) {
            return parse.getDayOfMonth();
        } else {
            return -1;
        }

    }

    /**
     * 获取指定日期格式的日期字符串是当月的上中下旬
     * @param date 日期字符串
     * @param format 日期格式
     * @return first 上旬；second 中旬；last 下旬
     */
    public static String getTenDays(String date, String format) {
        if (ObjectUtil.isEmpty(format)) {
            format = DATE_SPLIT_PATTERN;
        }

        LocalDate parse = LocalDate.parse(date, DateTimeFormatter.ofPattern(format));

        int day = parse.getDayOfMonth();
        if (day <= 10) {
            return "first";
        } else if (day <= 20) {
            return "second";
        } else {
            return "last";
        }
    }

    public static String getTenDaysChinese(String date, String format) {
        int month = DateUtil.getYMD(date, format, "m");
        String tenDays = DateUtil.getTenDays(date, format);
        String chineseTenDays;
        switch (tenDays) {
            case "first":
                chineseTenDays = "上旬";
                break;
            case "second":
                chineseTenDays = "中旬";
                break;
            case "last":
                chineseTenDays = "下旬";
                break;
            default:
                chineseTenDays = "上旬";
                break;
        }

        return month + "月" + chineseTenDays;

    }

    /**
     * 计算 from - to 中间相隔多少天
     * @param fromDate 开始时间
     * @param toDate 结束时间
     * @param format 格式
     * @return 相差天数
     */
    public static int sub(String fromDate, String toDate, String format) {
        LocalDate from = LocalDate.parse(fromDate, DateTimeFormatter.ofPattern(format));
        LocalDate to = LocalDate.parse(toDate, DateTimeFormatter.ofPattern(format));

        return to.compareTo(from);
    }

    /**
     * 字符串日期(y年M月d日)格式转换
     * @param baseDate
     * @return
     */
    public static LocalDate specialDateFormat(String baseDate){
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        Date parse = null;
        try {
            parse = dateFormat.parse(baseDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return parse.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /**
     * 校验日期格式 yyyy-MM-dd
     */
    public static boolean checkDateFormat(String date) {
        try {
            if (ObjectUtil.isEmpty(date)) {
                return false;
            }
            LocalDate.parse(date, DateTimeFormatter.ofPattern(DateUtil.DATE_SPLIT_PATTERN));
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 校验日期 yyyyMMdd 合法性
     * @param dateString
     * @return
     */
    public static Boolean validateDate(String dateString) {
        if (ObjectUtil.isEmpty(dateString)) {
            return false;
        }
        if (dateString.length()==4) {
            dateString = dateString+"0101";
        }
        if (dateString.length()==6) {
            dateString = dateString+"01";
        }
        Matcher matcher = VALIDATE_DATE.matcher(dateString);
        if (!matcher.matches()) {
            return false;
        }
        Integer date = Integer.valueOf(dateString);
        int year = date / 10000;
        int month = (date % 10000) / 100;
        int day = date % 100;
        //定义一个数组，数组里是每个月的合法天数
        int[] arr = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        //判断平年闰年
        if ( ( year % 4 == 0 && year % 100 != 0 ) || ( year % 400 == 0 ) ) {
            //闰年二月有29天
            arr[1] = 29;
        } else {
            //平年二月有28天
            arr[1] = 28;
        }

        //首先月份只有1到12月
        if (month > 0 && month < 13) {
            //天数从0到该月的最大天数
            if ( day <= arr[month - 1] && day > 0 ) {
                //如果合法，返回true
                return true;
            }
        }
        return false;
    }

    public static String formatStr(String time) {
        int yearIndex = time.indexOf("-", 0);
        int monthIndex = time.indexOf("-", yearIndex + 1);
        int dayIndex = time.indexOf(" ", monthIndex + 1);


        int hourIndex = time.indexOf(":", dayIndex + 1);
        int minuteIndex = time.indexOf(":", hourIndex + 1);
//        int secondIndex = time.length();

        String year = time.substring(0, yearIndex);
        String month = time.substring(yearIndex + 1, monthIndex);
        month = get2Str(month);
        String day = time.substring(monthIndex + 1, dayIndex);
        day = get2Str(day);


        String hour = time.substring(dayIndex + 1, hourIndex);
        hour = get2Str(hour);
        String minute = time.substring(hourIndex + 1, minuteIndex);
        minute = get2Str(minute);
        String second = time.substring(minuteIndex + 1);
        second = get2Str(second);

        return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;

    }

    private static String get2Str(String str) {
        if (str.length() == 1) {
            return "0" + str;
        } else if (str.length() == 2) {
            return str;
        }
        return str;
    }

}
